/**
 * User: 缪凯
 * Date: 12-8-14
 * Time: 上午11:04
 */

(function($){
    var eve = function (name, scope) {
        var e = this.events,
            oldstop = this.stop,
            args = Array.prototype.slice.call(arguments, 2),
            listeners = this.listeners(name),
            z = 0,
            f = false,
            l,
            indexed = [],
            queue = {},
            out = [],
            ce = eve.current_event = name,
            errors = [];
        for (var i = 0, ii = listeners.length; i < ii; i++)
            if ("zIndex" in listeners[i]) {
                indexed.push(listeners[i].zIndex);
                if (listeners[i].zIndex < 0) {
                    queue[listeners[i].zIndex] = listeners[i];
                }
            }
        indexed.sort(eve.numsort);

        while (indexed[z] < 0) {
            l = queue[indexed[z++]];
            out.push(l.apply(scope, args));
            if (eve.stop) {
                eve.stop = oldstop;
                return out;
            }
        }
        for (i = 0; i < ii; i++) {
            l = listeners[i];
            if ("zIndex" in l) {
                if (l.zIndex == indexed[z]) {
                    out.push(l.apply(scope, args));
                    if (stop) {
                        break;
                    }
                    do {
                        z++;
                        l = queue[indexed[z]];
                        l && out.push(l.apply(scope, args));
                        if (stop) {
                            break;
                        }
                    } while (l)
                } else {
                    queue[l.zIndex] = l;
                }
            } else {
                out.push(l.apply(scope, args));
                if (eve.stop) {
                    break;
                }
            }
        }
        this.stop = oldstop;
        this.current_event = ce;
        return out.length ? out : null;
    };

    $.extend(eve , {
        version: "0.3.4",
        has: "hasOwnProperty",
        separator: /[\.\/]/,
        wildcard: "*",
        fun: function(){},
        numsort:
            function (a, b) {
                return a - b;
            },
        current_event: "",
        stop: 0,
        events: {n: {}}
    });

    $.extend(eve , {
        listeners: function (name) {
            var names = name.split(separator),
                e = eve.events,
                item,
                items,
                k,
                i,
                ii,
                j,
                jj,
                nes,
                es = [e],
                out = [];
            for (i = 0, ii = names.length; i < ii; i++) {
                nes = [];
                for (j = 0, jj = es.length; j < jj; j++) {
                    e = es[j].n;
                    items = [e[names[i]], e[eve.wildcard]];
                    k = 2;
                    while (k--) {
                        item = items[k];
                        if (item) {
                            nes.push(item);
                            out = out.concat(item.f || []);
                        }
                    }
                }
                es = nes;
            }
            return out;
        },
        on: function (name, f) {
            var names = name.split(eve.separator),
                e = eve.events;
            for (var i = 0, ii = names.length; i < ii; i++) {
                e = e.n;
                !e[names[i]] && (e[names[i]] = {n: {}});
                e = e[names[i]];
            }
            e.f = e.f || [];
            for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
                return fun;
            }
            e.f.push(f);
            return function (zIndex) {
                if (+zIndex == +zIndex) {
                    f.zIndex = +zIndex;
                }
            };
        },
        stop: function () {
            eve.stop = 1;
        },
        nt: function (subname) {
            if (subname) {
                return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(eve.current_event);
            }
            return eve.current_event;
        },
        off: function (name, f) {
            var names = name.split(eve.separator),
                e,
                key,
                splice,
                i, ii, j, jj,
                cur = [eve.events];
            for (i = 0, ii = names.length; i < ii; i++) {
                for (j = 0; j < cur.length; j += splice.length - 2) {
                    splice = [j, 1];
                    e = cur[j].n;
                    if (names[i] != eve.wildcard) {
                        if (e[names[i]]) {
                            splice.push(e[names[i]]);
                        }
                    } else {
                        for (key in e) if (e[has](key)) {
                            splice.push(e[key]);
                        }
                    }
                    cur.splice.apply(cur, splice);
                }
            }
            for (i = 0, ii = cur.length; i < ii; i++) {
                e = cur[i];
                while (e.n) {
                    if (f) {
                        if (e.f) {
                            for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {
                                e.f.splice(j, 1);
                                break;
                            }
                            !e.f.length && delete e.f;
                        }
                        for (key in e.n) if (e.n[has](key) && e.n[key].f) {
                            var funcs = e.n[key].f;
                            for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {
                                funcs.splice(j, 1);
                                break;
                            }
                            !funcs.length && delete e.n[key].f;
                        }
                    } else {
                        delete e.f;
                        for (key in e.n) if (e.n[has](key) && e.n[key].f) {
                            delete e.n[key].f;
                        }
                    }
                    e = e.n;
                }
            }
        },
        unbind: this.off,
        once: function (name, f) {
            var f2 = function () {
                var res = f.apply(this, arguments);
                eve.unbind(name, f2);
                return res;
            };
            return eve.on(name, f2);
        },
        toString:function () {
            return "You are running Eve " + this.version;
        }
    });

    var R = function(first){
        if (R.is(first, "function")) {
            return R.loaded ? first() : eve.on("raphael.DOMload", first);
        } else if (R.is(first, array)) {
            return R._engine.create[R.apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);
        } else {
            var args = Array.prototype.slice.call(arguments, 0);
            if (R.is(args[args.length - 1], "function")) {
                var f = args.pop();
                return R.loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () {
                    f.call(R._engine.create[apply](R, args));
                });
            } else {
                return R._engine.create[apply](R, arguments);
            }
        }
    };

    $.extend(R , {
        apply: "apply",
        loaded: false,
        Str: String,
        lowerCase: R.Str.prototype.toLowerCase,
        isnan: {"NaN": 1, "Infinity": 1, "-Infinity": 1},
        has: "hasOwnProperty",
        objectToString: Object.prototype.toString,
        version: "2.1.0",
        eve: eve,
        type: (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML")
    });

    $.extend(R , {
        is: function (o, type) {
            type = R.lowerCase.call(type);
            if (type == "finite") {
                return !R.isnan[R.has](+o);
            }
            if (type == "array") {
                return o instanceof Array;
            }
            return  (type == "null" && o === null) ||
                (type == typeof o && o !== null) ||
                (type == "object" && o === Object(o)) ||
                (type == "array" && Array.isArray && Array.isArray(o)) ||
                R.objectToString.call(o).slice(8, -1).toLowerCase() == type;
        }
    });

    var raphael = function(canvas , first){
        $.extend(raphael.prototype , {
            canvas: canvas,
            R: R(first)
        });
    };


    $.fn.draw = function(first){

        return new raphael(this , first);
    }
})(jQuery);



